package com.shelpe.services.sinbadgateway.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.shelpe.services.sinbadgateway.client.AlgorithmClient;
import com.shelpe.services.sinbadgateway.client.AlgorithmClient.SemiautoDto;
import com.shelpe.services.sinbadgateway.client.ProxyClient;
import com.shelpe.services.sinbadgateway.client.SemiautoClient;
import com.shelpe.services.sinbadgateway.client.SemiautoClient.KeywordsDto;
import com.shelpe.services.sinbadgateway.client.SemiautoClient.KeywordsLog;
import com.shelpe.services.sinbadgateway.client.SemiautoClient.KeywordsLog.Action;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Controller
@RequestMapping("/sinbadgateway")
@Slf4j
@Getter
@Setter
public class SemiautoController {

	@Autowired
	SemiautoClient semiautoClient;
	
	@Autowired
	AlgorithmClient algorithmClient;

	@Autowired
	ProxyClient proxyClient;

	private ExecutorService threadPool = Executors.newFixedThreadPool(4);

	@RequestMapping(method = RequestMethod.POST, value = "/semiautos/exec")
	public @ResponseBody Object exec(@RequestBody JSONArray prices, 
			@RequestParam Long userId, @RequestParam(required = false) String nick){
		log.info("semiautos/exec paramters userId:{} nick:{} prices:{}", userId, nick, prices);
		//设置出价
		String ret = "";
		if(nick == null){
			nick = semiautoClient.getNick(userId);
		}
		ret = proxyClient.setPricevon(nick, JSON.toJSONString(prices));
		log.info("set prices result:{}", ret);
		if(ret.contains("simba_keywords_pricevon_set_response")){
			JSONObject obj = JSON.parseObject(ret);
			JSONArray arr = obj.getJSONObject("simba_keywords_pricevon_set_response").
					getJSONObject("keywords").getJSONArray("keyword");
			JSONObject wordjson;
			com.shelpe.services.sinbadgateway.model.Keyword keyword;
			KeywordsLog log = null;
			List<KeywordsLog> logs = new ArrayList<KeywordsLog>();
			for(Iterator<Object> iter = arr.iterator(); iter.hasNext();){
				wordjson = (JSONObject)iter.next();
				keyword = JSON.parseObject(wordjson.toJSONString(), com.shelpe.services.sinbadgateway.model.Keyword.class);
				semiautoClient.update(keyword, userId);
				log = new KeywordsLog();
				log.setKeywordId(keyword.getKeywordId());
				log.setUpdatedTime(new Date());
				log.setAction((byte)Action.SEMIAUTO_EXEC.getValue());
				log.setAdgroupId(keyword.getAdgroupId());
				log.setKeyword(keyword.getWord());
				log.setNewIntVal(keyword.getMaxPrice());
				log.setNote(wordjson.toJSONString());
				logs.add(log);
			}
			semiautoClient.keywordLog(logs);
		}
		return ret;
	}

//	@RequestMapping("/semiautos/{semiautoId}/exec")
//	public @ResponseBody Object exec(@PathVariable("semiautoId")Long semiautoId, @RequestParam(required=false)String campaignId, 
//			@RequestParam(required=false)String adgroupId, @RequestParam(required=false)String keywordIds, @RequestParam(required=false)boolean matched){
//		List<Long> adgroupIDs = semiautoClient.getAdgroupIds(adgroupId, campaignId);
//		final Long userId = semiautoClient.getUserId(semiautoId);
//		final List<KeywordsDto> dtos = new ArrayList<KeywordsDto>();
//		final SemiautoDto semiautoDto = algorithmClient.findSemiauto(semiautoId);
//		for(Long adgroupid : adgroupIDs){
//			KeywordsDto dto = semiautoClient.getKeywords(semiautoId, adgroupid, userId, keywordIds, matched);
//			dtos.add(dto);
//		}
//		return prices(dtos, semiautoDto.getDevice(), userId, null);		
//	}
	
	@RequestMapping("/semiautos/{semiautoId}/keywords")
	public @ResponseBody Object getkeywords(@PathVariable("semiautoId")Long semiautoId, @RequestParam(required=false)String campaignId, 
			@RequestParam(required=false)String adgroupId, @RequestParam(required=false, defaultValue="true")boolean matched) throws InterruptedException, ExecutionException{
			log.debug("semiautoId:{}, campaignId:{}, adgroupId:{}", semiautoId, campaignId, adgroupId);
			Long userId = semiautoClient.getUserId(semiautoId);
			log.debug("userId:{}", userId);
			final List<KeywordsDto> dtos = new ArrayList<KeywordsDto>();
			final SemiautoDto semiautoDto = algorithmClient.findSemiauto(semiautoId);
			List<Long> adgroupIds = semiautoClient.getAdgroupIds(adgroupId, campaignId);
			
			List<FutureTask<KeywordsDto>> futures = new ArrayList<FutureTask<KeywordsDto>>();
			FutureTask<KeywordsDto> future;
			
			for(Long adgroupid : adgroupIds){
				Future<KeywordsDto> f = threadPool.submit(new getKeywrordTask<KeywordsDto>(semiautoId, adgroupid, userId, matched));
				future = (FutureTask<KeywordsDto>)f;
				futures.add(future);
//				KeywordsDto dto = semiautoClient.getKeywords(semiautoId, adgroupid, userId, null, matched);
//				dtos.add(dto);
			}
			
			for(Future<KeywordsDto> f : futures){
				dtos.add((KeywordsDto)f.get());
			}
			
			JSONObject obj = new JSONObject();
			obj.put("response", dtos);
			obj.put("device", semiautoDto.getDevice());
		return obj;
	}

	private Object prices(List<KeywordsDto> dtos,  int device, Long userId, String nick ){
		//设置出价
		String ret = "";
		if(nick == null){
			nick = semiautoClient.getNick(userId);
		}
		JSONArray array = new JSONArray();
		List<String> pricesList = toPriceParams(dtos, device);
		if(!pricesList.isEmpty()){
			for(String prices:pricesList){
				ret = proxyClient.setPricevon(nick, prices);
				log.info("set prices result:{}", ret);
				
				if(ret.contains("simba_keywords_pricevon_set_response")){
					JSONObject obj = JSON.parseObject(ret);
					JSONArray arr = obj.getJSONObject("simba_keywords_pricevon_set_response").
					getJSONObject("keywords").getJSONArray("keyword");
					JSONObject wordjson;
					com.shelpe.services.sinbadgateway.model.Keyword keyword;
					for(Iterator<Object> iter = arr.iterator(); iter.hasNext();){
						wordjson = (JSONObject)iter.next();
						keyword = JSON.parseObject(wordjson.toJSONString(), com.shelpe.services.sinbadgateway.model.Keyword.class);
						semiautoClient.update(keyword, userId);
					}
					array.add(ret);
				}
			}
			JSONObject obj = new JSONObject();
			obj.put("old_data", dtos);
			obj.put("new_data", array);
			obj.put("device", device);
			return obj;
		}else{
			return "prices is null";
		}
	}
	
	/**
	 * 将dtos转换为 出价API需要的字符串参数
	 * @param dtos
	 * @return
	 */
	private List<String> toPriceParams(List<KeywordsDto> dtos, int device){
		//[{"keywordId":"222886332274","maxPrice":88,"isDefaultPrice":0,"matchScope":4}]
		JSONArray array = new JSONArray();
		JSONObject obj;
		
		List<String> rets = new ArrayList<String>();
		
		for(KeywordsDto dto : dtos){
			for(com.shelpe.services.sinbadgateway.client.SemiautoClient.Keyword keyword : dto.getWords()){
				if(keyword.isMatched()){
					obj = new JSONObject();
					obj.put("keywordId", keyword.getKeywordID());
					if(device == 1){
						obj.put("maxMobilePrice", keyword.getMobilePrice());//dto.getAdgroup().getMobileDiscount()*keyword.getPrice()/100
						obj.put("mobileIsDefaultPrice", 0);//keyword.getAsDefaultMobilePrice()?1:0
					}else if(device == 2){
						obj.put("maxPrice", keyword.getPrice());
						obj.put("isDefaultPrice", keyword.getAsDefaultPrice()?1:0);
					}
					obj.put("matchScope", keyword.getNewMatchScope());
					array.add(obj);
					if(array.size() > 30){
						rets.add(array.toJSONString());
						array.clear();
					}
				}
			}
			rets.add(array.toJSONString());
		}
		if(log.isInfoEnabled()){
			for(String str : rets){
				log.info("prices:{}", str);
			}
		}
		return rets;
	}
	
	@SuppressWarnings("hiding")
	private class getKeywrordTask<KeywordsDto> implements Callable<KeywordsDto>{
		private Long semiautoId;
		private Long adgroupId;
		private Long userId;
		private boolean matched;
		public getKeywrordTask(Long semiautoId, Long adgroupId, Long userId, boolean matched){
			this.semiautoId = semiautoId;
			this.adgroupId = adgroupId;
			this.userId = userId;
			this.matched = matched;
		}
		@SuppressWarnings("unchecked")
		@Override
		public KeywordsDto call() throws Exception {
			return (KeywordsDto) semiautoClient.getKeywords(semiautoId, adgroupId, userId, null, matched);
		}
		
	}
	
}
